﻿using System;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Collections.Generic;
using NeuronDotNet.Controls;
using NeuronDotNet.Core;
using NeuronDotNet.Core.Backpropagation;
using NeuronDotNet.Samples.CharacterRecognition;
using NeuronDotNet.Samples.OCR.layoutsstategies;
using NeuronDotNet.Samples.OCR;
using System.Windows.Forms;

namespace ICRWrapper
{
    public class ICRWrapper
    {
        private static readonly string[] letters = 
        {
            "A", "B", "C", "D", "E", "F", "G", "H", "I",
            "J", "K", "L", "M", "N", "O", "P", "Q", "R",
            "S", "T", "U", "V", "W", "X", "Y", "Z"
        };

        private string RecognizeLetter(double[] letterVector)
        {
            //This var mean index in string[] letters(English alphabet).
            int winner = 0;
            int current = 1;

            //ClearListBoxAndResultBufferedPanel();

            while (current < Alphabet.LetterCount)
            {
                try
                {
                    using (Stream stream = File.Open(
                      GeneratePathToNetwork(winner, current),
                      FileMode.Open))
                    {
                        IFormatter formatter = new BinaryFormatter();
                        var network = (INetwork)formatter.Deserialize(stream);
                        double[] output = network.Run(letterVector);

                        if (output[1] > output[0])
                        {
                            winner = current;
                        }
                    }
                    current++;
                }
                catch (Exception)
                {
                    //ShowFailedToLoadSavedNeuralNetworkErrorMessageBox();
                }
            }
            return letters[winner];
        }

        private string GeneratePathToNetwork(int winner, int current)
        {
            String pathTemplate = "{0}\\Networks\\{1}{2}.ndn";
            string pathToNetwork = String.Format(CultureInfo.InvariantCulture,
                pathTemplate,
                Application.StartupPath,
                winner.ToString("00"),
                current.ToString("00")
            );
            return pathToNetwork;
        }

        /// <summary>
        /// Recognize word.
        /// </summary>
        public string Recognize(LetterICRWrapper letter)
        {
            //HideResultAndPresultLabel();
            //divisionBuilder curry for division full image 
            //on single letter image.
            var divisionBuilder = new DivisionBuilder(letter.Letter);
            //imageLayout can create list current clipped letters.
            var imageLayout = new NeuronDotNet.Samples.OCR.ImageLayout(divisionBuilder);
            //in this var will accumulate recognized word.
            string word = String.Empty;
            List<Letter> letterList = imageLayout.GetClippedLetters();

            foreach (Letter iLetter in letterList)
            {
                //20x20 = 400 - the number of input neurons of every neural network
                double[] letterVector = iLetter.GetEquivalentVector(20, 20);
                word += RecognizeLetter(letterVector);
            }

            //ShowResult(word);
            return word;
        }


    }
}
